iT邦幫忙

2025 iThome 鐵人賽

DAY 24
0

同步(Synchronous)

  • 同一時間只做一件事,一次只跑一段程式碼。
    就像 JavaScript 語法解析器一樣,從上到下一行一行執行。

當 JavaScript 載入全域執行環境(Global Execution Context)
也許呼叫了某個函式建立新的執行環境(Function Execution Context)
等函式執行完回到全域環境後結束,一切都是「同步」進行的。

非同步(Asynchronous)

  • 同一時間內處理不只一件事,也就是「程式碼執行的先後順序不一定固定」。
    主程式會繼續往下執行,而非同步任務會被暫存起來
    等到主程式執行完、JavaScript 引擎有空閒後才執行。

這讓 JavaScript 在「單執行緒」的情況下,仍能同時處理多個事件。

在瀏覽器前端很常見的情境是「讀取資料」

例如一個部落格網站,網頁一打開就必須:

  • 處理畫面上的互動行為(滾動、點擊、動畫)。
  • 同時向後端請求文章資料。

若採用同步方式來拉資料,整個網站在資料回來之前都會「卡住」。
這就是非同步機制存在的意義:讓畫面能繼續互動,同時背景抓資料。

瀏覽器內的組成角色

瀏覽器除了 JavaScript 引擎外,還有許多其他模組在協同運作:

  • JavaScript 引擎:負責執行程式。
  • 渲染引擎:負責畫面繪製(HTML、CSS)。
  • 網路模組:負責 HTTP 請求、API 資料傳輸。

JavaScript 可能會在執行過程中請求這些模組的幫忙

  • 改變畫面內容(由渲染引擎處理)
  • 觸發網路請求(由網路模組處理)
  • 設定計時器(由 Web API 處理)

注意:
這些「非同步工作」並不在 JavaScript 引擎裡面執行,它們由瀏覽器的其他部分負責。
在 JavaScript 引擎看來,它仍是「同步」在跑,只是外部有機制幫它記錄該做的事。

Event Queue 與 Event Loop

這兩個東西不屬於 JavaScript 本身,而是瀏覽器的一部分。

JavaScript 引擎的組成

執行環境堆疊(Execution Stack)
當函式被呼叫時,會建立一個新的執行環境;
若在此函式內又呼叫其他函式,會在上方再疊一層。
上層未結束前,下層無法執行(包含全域環境)。

  • 記憶體堆積(Memory Heap)
  • 儲存變數、物件、函式的記憶體空間。

如果某個堆疊執行太久(例如死循環),整個主程式就會被「卡死」。

JavaScript Runtime Environment (JRE)

  • Event Queue(事件佇列)
  • Event Table(事件表)
  • Web API(瀏覽器提供的功能)
  • Event Loop(事件循環器)

Event Queue(事件佇列)

有些函式(例如 setTimeout、setInterval)其實不是 JavaScript 內建的,而是瀏覽器提供的 Web API。
常見的 Web API :

  • 操作 DOM:document.getElementById
  • AJAX:XMLHttpRequest
  • 計時:setTimeoutsetInterval

這些 API 的工作通常比較耗時,因此瀏覽器會先把它們交給 Web API 模組處理,
而不是讓主執行緒「乾等」。等到處理完成後,才會將結果丟進 Event Queue。

Event Queue 的運作流程

以 setTimeout 為例:

function executeAfterDelay() {
  console.log("一秒之後才會執行");
}

setTimeout(executeAfterDelay, 1000);
console.log("我會先被執行");

執行步驟如下:

  • JavaScript 執行到 setTimeout 時,交給瀏覽器計時(不會阻塞主程式)。
  • 主程式繼續往下執行(console.log("我會先被執行"))。
  • 計時完畢後,瀏覽器把要執行的函式推進 Event Queue。
  • 當主程式執行完畢、堆疊清空後,Event Loop 會把佇列中的函式取出執行。
function executeAfterDelay() {
  console.log("應該要馬上執行");
}
setTimeout(executeAfterDelay, 0);

console.log("應該要最後執行");

即使設定 0ms,仍會先執行主程式,因為 Event Queue 的任務會等堆疊清空後才跑。

Event Table(事件表)

Event Table 是一個用來記錄「哪些事件完成後要執行什麼函式」的資料集合。
當你執行 setTimeout() 時
JavaScript 會把:

  • 要執行的函式
  • 附加資訊(例如等待秒數)

一起放進 Event Table。

等時間到(非同步目的達成),再把該函式正式推進 Event Queue,等待主線程空閒後執行。

這個流程讓 JavaScript不會因等待資料或時間而卡住整個程式。


參考資料


上一篇
Day23|ES6 延伸語法 — 解構賦值、展開運算子與物件語法增強
系列文
程式小白的 30 天轉職挑戰24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言